<?php
/**
 * Created by PhpStorm.
 * User: tom_xia
 * Date: 2017/11/30
 * Time: 17:14
 */
class Tools
{
    public static function auth_code($string, $operation = 'DECODE', $key = '', $expiry = 0) {
        /*
            动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
            加入随机密钥，可以令密文无任何规律，即便是原文和密钥完全相同，加密结果也会每次不同，增大破解难度。
            取值越大，密文变动规律越大，密文变化 = 16 的 $ckey_length 次方
            当此值为 0 时，则不产生随机密钥
        */
        $ckey_length = 4;
        $key = md5($key != '' ? $key : "fdsfdf43535svxfsdfdsfs"); // 此处的key可以自己进行定义，写到配置文件也可以
        $keya = md5(substr($key, 0, 16));

        $keyb = md5(substr($key, 16, 16));
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
        $cryptkey = $keya.md5($keya.$keyc);
        $key_length = strlen($cryptkey);
        // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
        // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
        $string_length = strlen($string);

        $result = '';
        $box = range(0, 255);

        $rndkey = array();
        for($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }

        for($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }

        for($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if($operation == 'DECODE') {
            if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
            return $keyc.str_replace('=', '', base64_encode($result));
        }
    }
    public static function get_client_ip(){
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")){
            $ip = getenv("HTTP_CLIENT_IP");
        }else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")){
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        }else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
            $ip = getenv("REMOTE_ADDR");
        else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
            $ip = $_SERVER['REMOTE_ADDR'];
        else
            $ip = "unknown";
        return($ip);
    }
    public static function htmlFilter($str){
        return htmlspecialchars($str);
    }
    public static function uniqid($unique = '') {
        if (!empty($unique)) {
            $chars = md5($unique);
        } else {
            $chars = md5(uniqid(mt_rand(), true));
        }
        $uuid = substr($chars, 0, 8) . '-';
        $uuid .= substr($chars, 8, 4) . '-';
        $uuid .= substr($chars, 12, 4) . '-';
        $uuid .= substr($chars, 16, 4) . '-';
        $uuid .= substr($chars, 20, 12);
        return strtoupper($uuid);
    }
    /**
     * @desc 通过用户的uuid获得存储用户信息的redis hash表名或者队列名称
     * @param   $uuid
     * @param   $prefix redis key的前缀
     * @param   $nums key个数
     * @param   $bit hash后缀位数，其中$bit必须>=$hashNums的位数
     * @return string hash key
     */
    public static function getHashSubfixByUUID($uuid,$prefix="",$nums = 100,$bit=3)
    {
        if(strlen($nums) > $bit){
            return null;
        }
        //1.获取uuid的循环冗余码,并取正整数
        $code = sprintf("%u",crc32($uuid));
        //2.获取hash表后缀
        $format = "%'0".$bit."d";
        if($nums == 1){
            $hashSubfix = 0;
        }else{
            $hashSubfix = sprintf($format,($code % $nums));
        }
        return $prefix.$hashSubfix;
    }
    public static function random($length, $numeric = 0) {
        $seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
        $seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
        if($numeric) {
            $hash = '';
        } else {
            $hash = chr(rand(1, 26) + rand(0, 1) * 32 + 64);
            $length--;
        }
        $max = strlen($seed) - 1;
        for($i = 0; $i < $length; $i++) {
            $hash .= $seed{mt_rand(0, $max)};
        }
        return $hash;
    }

    //http请求
    public static function curl($url, $data = [], $type = "get", $https = false, $header = "")
    {
        $ch = curl_init();//curl句柄
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);//5秒的超时时间
        if ($type == "get") {
            $url = $url . "?" . http_build_query($data);
        }
        if ($header) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if ($type == "post") {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        if ($https == true) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
        } else {
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        }
        $result = curl_exec($ch);
        if ($result && empty(curl_error($ch))) {
            curl_close($ch);
            return $result;
        } else {
            $error = curl_error($ch);
            curl_close($ch);
            throw new \Exception("curl错误:" . $error);
        }
    }

    public static function UUID($namespace = '') {
        $guid = '';
        $uid = uniqid("", true);
        $data = $namespace;
        $data .= isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : ""; //
        $data .= isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; //$_SERVER['HTTP_USER_AGENT'];
        $data .= isset($_SERVER['LOCAL_ADDR']) ? $_SERVER['LOCAL_ADDR'] : ""; //$_SERVER['LOCAL_ADDR'];
        $data .= isset($_SERVER['LOCAL_PORT']) ? $_SERVER['LOCAL_PORT'] : ""; //$_SERVER['LOCAL_PORT'];
        $data .= isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ""; //$_SERVER['REMOTE_ADDR'];
        $data .= isset($_SERVER['REMOTE_PORT']) ? $_SERVER['REMOTE_PORT'] : ""; //$_SERVER['REMOTE_PORT'];
        $hash = strtoupper(hash('ripemd128', $uid . $guid . md5($data)));
        $guid = substr($hash, 0, 8) .
            '-' .
            substr($hash, 8, 4) .
            '-' .
            substr($hash, 12, 4) .
            '-' .
            substr($hash, 16, 4) .
            '-' .
            substr($hash, 20, 12);
        return $guid;
    }
    //加密id
    public static  function encodeID($ID,$slat_type="common")
    {
        return static::auth_code($ID."|".time()."|".mt_rand(1000,9999),"ENCODE",$slat_type);
    }
    //解密id
    public  static  function decodeID($decodeStr,$slat_type="common",$isExpire=false,$expireTime=3600){
        $newDecodeStr =  static::auth_code($decodeStr,"DECODE",$slat_type);
        if($newDecodeStr === ""){
            return "";
        }
        $arr = explode("|",$newDecodeStr,3);
        if(count($arr) != 3 ){
            return "";
        }
        //过期时间
        if($isExpire && $expireTime >0 ){
            if($arr[1]+$expireTime <= time()){
                return "";
            }
        }
        return $arr[0];
    }

    public static function xssFilter($str){
        return htmlspecialchars($str);
    }
    /**
     * @desc 创建script标签，用于播放视频
     * @param $url
     * @param array $data
     * @return string
     */
    public static function createPlayHtml($url,$isScript = true,$data=[])
    {
        $playerUrl = SITE_BASE_URL . "/assets/js/sewise-player/player/sewise.player.min.js";
        $params = array();
        if (isset($data['title'])) {
            $params['title'] = "";
        }
        $params['autostart'] = isset($data['autostart']) ? $data['autostart'] : "true";
        $params['starttime'] = isset($data['starttime']) ? $data['starttime'] : 0;
        $params['buffer'] = isset($data['buffer']) ? $data['buffer'] : 5;
        $params['skin'] = isset($data['skin']) ? $data['skin'] : "vodWhite";
        $params['topbardisplay'] = isset($data['topbardisplay']) ? $data['topbardisplay'] : "disable";
        $ext = pathinfo($url, PATHINFO_EXTENSION);
        if (in_array($ext, array("flv", "mp4", "m3u8", "m4v"))) {
            $params['server'] = "vod";
            $params['type'] = $ext == "m4v" ? "mp4" : $ext;
            $params['videourl'] = urlencode($url);
//        $params["controlbardisplay"] = "disable";
        } else {
            $params['server'] = isset($data['server']) ? $data['server'] : "";
            $params['type'] = isset($data['type']) ? $data['type'] : "";
        }
        $paramsStr = "";
        foreach ($params as $k => $v) {
            $paramsStr .= "{$k}={$v}&";
        }
        $paramsStr = trim($paramsStr, "&");
        $u = $playerUrl . "?" . $paramsStr;
        if ($isScript) {
            return "<script src='{$u}'></script>";
        } else {
            return $u;
        }
    }
}